'''
Created on 12/02/2010

@author: eh01
'''
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import os
import mywsdl
import time
import threading
import mysoaptest
import mysoap
import httpclient
import re

# A html page to display the results for the sample request
html_request_response = '''<html>
    <head>
        <title>Request-Response Sample Message</title>
    </head>
    <body>
        <h1>Request-Response Sample Message</h1>
        <h2>Request Message</h2>
        <textarea cols="150" rows="50">{0}</textarea>
        <h2>Response Message</h2>
        <textarea cols="150" rows="50">{1}</textarea>
    </body>
</html>
'''

my_spaces = {
            'Application/S000001E':'Application/S000001E',
            'Application/S000001E/ApplicationID':'?',
            'ReceiptAcknowledgementSignal/ReceiptAcknowledgement':'ReceiptAcknowledgementSignal/ReceiptAcknowledgement',
            'ReceiptAcknowledgementSignal/ReceiptAcknowledgement/Timestamp':'?',            
            'StandardBusinessMessageHeader':'StandardBusinessMessageHeader',
            'StandardBusinessMessageHeader/BusinessScope':'StandardBusinessMessageHeader/BusinessScope',
            'StandardBusinessMessageHeader/BusinessScope/Type':'BusinessCollaboration',
            'StandardBusinessMessageHeader/DocumentIdentification':'StandardBusinessMessageHeader/DocumentIdentification',                
            'StandardBusinessMessageHeader/DocumentIdentification/CreationDateTime':'?',
            'StandardBusinessMessageHeader/DocumentIdentification/InstanceID':'?',
            'StandardBusinessMessageHeader/DocumentIdentification/Standard':'?',
            'StandardBusinessMessageHeader/DocumentIdentification/Type':'?',
            'StandardBusinessMessageHeader/DocumentIdentification/TypeVersion':'?',
            'StandardBusinessMessageHeader/ReceiverPartner':'StandardBusinessMessageHeader/ReceiverPartner',
            'StandardBusinessMessageHeader/ReceiverPartner/Authority':'?',
            'StandardBusinessMessageHeader/ReceiverPartner/ID':'?',
            'StandardBusinessMessageHeader/ReceiverPartner/ProcessRole':'?',
            'StandardBusinessMessageHeader/SenderPartner':'StandardBusinessMessageHeader/SenderPartner',
            'StandardBusinessMessageHeader/SenderPartner/Authority':'?',
            'StandardBusinessMessageHeader/SenderPartner/ID':'?',
            'StandardBusinessMessageHeader/SenderPartner/ProcessRole':'?',                
            'StandardBusinessMessageHeader/Version': '?'
          }

# pattern to match for the samplerequest
samplerequest_path_p = re.compile(r'/samplerequest\?host=([\w\W]*)&port=(\d*)')
# pattern to match for wsdl request
wsdl_path_p = re.compile(r'/services/(.*)')
# pattern to match for xsd request
xsd_path_p = re.compile(r'/biv/(.*)')
# pattern to match for ws call
ws_path_p = re.compile(r'/services/(.*)')

class RequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        try:
            print "GET on {0}".format(self.path)
            # Home Page
            if self.path == '/':
                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                self.wfile.write('<html><h1>Hello World!</h1></html>')
            # Issues the sample request 
            elif samplerequest_path_p.match(self.path):
                m = samplerequest_path_p.match(self.path)
                dest_host = m.group(1)
                dest_port = m.group(2)
                (sample_request, (code, response)) = self.handle_GET_sample_request(dest_host, dest_port)
                print "Response code:{0}".format(code)
                print "Response xml:{0}".format(response)
                self.send_response(code)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                self.wfile.write(html_request_response.format(sample_request, response))
            # handles requests for xsd files
            elif xsd_path_p.match(self.path):
                m = xsd_path_p.match(self.path)
                # removes the leading forward slash on the path e.g. /path/to -> path/to
                xsd_file_path= m.group(0)[1:]
                self.send_response(200)
                self.send_header('Content-type', 'text/xml')
                self.end_headers()
                content_as_string = mywsdl.get_raw_wsdl_file(os.path.join('../../MyeDAIS2.3.0r2Artefacts', xsd_file_path)).read()
                self.wfile.write(content_as_string)
            # handles request for wsdl files                
            elif wsdl_path_p.match(self.path):
                m = wsdl_path_p.match(self.path)
                wsdl_file_name = m.group(1)
                self.send_response(200)
                self.send_header('Content-type', 'text/xml')
                self.end_headers()
                content_as_string = mywsdl.get_raw_wsdl_file(os.path.join(mysoap.wsdl_relative_path, wsdl_file_name)).read()
                self.wfile.write(content_as_string)
            else:
                self.send_error(404)
        except IOError:
            self.send_error(404)
    
    def do_POST(self):
        print "POST on {0}".format(self.path)   
        content_length = self.headers.getheader('Content-Length')
        soap_message = self.rfile.read(int(content_length))
        print "Message received: {0}".format(soap_message)
        # handles ws calls
        if ws_path_p.match(self.path):
            m = ws_path_p.match(self.path)
            ws_name = m.group(1)
            soap_action = self.headers.getheader('Soapaction')
            operation_name = soap_action.split('/')[-1].replace('"', '').replace("'", '')
            print "operation_name is {0}".format(operation_name)
            wsdl_file_name = "{0}.wsdl".format(ws_name)
            (extracted_content, reply_to_address) = mysoap.parse_soap_message(wsdl_file_name, soap_message, mysoaptest.mapping)
            # copy the fields in the received message to spaces
            for key, value in extracted_content.items():
                if value:
                    spaces_uris = mysoaptest.mapping[key]
                    # for keys with non empty lists, look in mapping to find the spaces uris for the key
                    if len(value) == 1:
                        for spaces_uri in spaces_uris:
                            # assume just one value
                            my_spaces[spaces_uri] = value[0] 
            print "reply_to_address is {0}".format(reply_to_address)
            reply_to_address = reply_to_address.replace('localhost:8080', 'edais.daf.gov.au').replace('http', 'https')
#            reply_to_address = reply_to_address.replace('localhost:8001', 'localhost:8088')
            print "hacked reply_to_address is {0}".format(reply_to_address)
            print extracted_content
#            (response_soap_message, response_soap_action) = mysoap.generate_soap_message_for_service(wsdl_file_name, operation_name, 'output', False, True, reply_to_address, mysoaptest.mapping, my_spaces , {'spear_ref':'S000001E'})
            (response_soap_message, response_soap_action) = mysoap.generate_soap_message_for_service(wsdl_file_name, operation_name, 'output', True, True, reply_to_address, mysoaptest.mapping, my_spaces , {'spear_ref':'S000001E'})
            print "response soap message: {0}".format(response_soap_message)
            self.send_response(200)        
            self.send_header('Content-Type', 'text/xml;charset=UTF-8')
            self.send_header('SOAPAction', response_soap_action)
            self.end_headers()
            self.wfile.write(response_soap_message)            
            # if it is a responder ws call, call back the initiator with a 'Accept'
            if ws_name.find('Responder') != -1:
                # look for the corresponding initiator ws
                initiator_ws = ws_name.replace('Responder', 'Initiator')
                # generate a soap message for the Accept operation
#                (async_soap_message, async_soap_action) = mysoap.generate_soap_message_for_service(initiator_ws + ".wsdl", 'Accept', 'input', False, True, reply_to_address, mysoaptest.mapping, my_spaces , {'spear_ref':'S000001E'})
                (async_soap_message, async_soap_action) = mysoap.generate_soap_message_for_service(initiator_ws + ".wsdl", 'Accept', 'input', True, True, reply_to_address, mysoaptest.mapping, my_spaces , {'spear_ref':'S000001E'})
                print "asyn response soap message: {0}".format(async_soap_message)
                async_request_endpoint = reply_to_address
                async_soap_action = 'https://edais.daf.gov.au/CreateReferral_Initiator.2.3.0r2/Accept'
                async_http_headers = {'Content-Type':'text/xml;charset=UTF-8',
                    'SOAPAction':  async_soap_action}    
                # Create the async request        
                print "async response headers: {0}".format(async_http_headers)
                async_request = AsyncRequest(async_soap_message, async_request_endpoint, async_http_headers)
                async_request.start()                    
        else:
            self.send_response(404) 
            self.send_error(404, "Endpoint Web service not found.")
            return

    def handle_GET_sample_request(self, dest_host, dest_port):
        reply_to = 'http://{0}:{1}/services/CreateReferral_Initiator.2.3.0r2'.format(self.server.network_hostname, self.server.network_port)
        (soap_message, soap_action) = mysoap.generate_soap_message_for_service('CreateReferral_Responder.2.3.0r2.wsdl', 'Propose', 'input', True, True, None, None, None, None, reply_to)
        request_endpoint = 'http://{0}:{1}{2}'.format(dest_host, dest_port, '/services/CreateReferral_Responder.2.3.0r2')
        print "Sending sample message to endpoint {0}".format(request_endpoint)
        http_headers = {'Content-Type':'text/xml;charset=UTF-8',
                'SOAPAction':  soap_action}
        return (soap_message, httpclient.send_request(request_endpoint, soap_message, http_headers))
        
class MyHTTPServer(HTTPServer):
    
    def __init__(self, hostname, port, network_hostname, network_port):
        HTTPServer.__init__(self, (hostname, port), RequestHandler)
        self.network_hostname = network_hostname
        self.network_port = network_port
        
    def shutdown_server(self):
        self.socket.close()
        print 'shutdown server'
    
class AsyncRequest(threading.Thread):
    
    def __init__(self, request_data, request_endpoint, http_headers):
        threading.Thread.__init__(self)
        self.request_endpoint = request_endpoint
        self.request_data = request_data
        self.http_headers = http_headers
        
    def run(self):
        time.sleep(2)
        print 'Sending soap message to endpoint: {0}'.format(self.request_endpoint)
        (code, response) = httpclient.send_request(self.request_endpoint, self.request_data, self.http_headers)
        print "async response code: {0}".format(code)
        print "async response message: {0}".format(response)
        